﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Xml;
using QDT.Common;
using QDT.Core.Domain;
using QDT.Core.Members;
using QDT.P2B.Domain.Messages;
using QDT.Web.Code.Enums;
using QDT.Web.GenerageRodomKey;
using QDT.Web.KeyAlogrithm;
using QDT.Web.Models;

namespace QDT.Web.Controllers
{
    public partial class UserController
    {
        public ActionResult Account()
        {
            return View(User);
        }

        [HttpPost]
        public ActionResult AccountSetting(AccountSettingModel model)
        {
            if (!ModelState.IsValid) return Error();
            if (User.ID != model.Id) return Error("信息错误");

            User user = _userService.GetUserByID(model.Id);
            bool isChange = false;
            if (!string.IsNullOrEmpty(model.Password))
            {
                if (model.PasswordOld.Hash().Equals(user.Password))
                {
                    user.ChangePassword(model.Password);
                    isChange = true;
                }
            }
            if (isChange)
            {
                _userService.UpdateUser(user);
                return Success("账户修改成功");
            }
            return Error("原始密码不正确");
        }

        public ActionResult SafePassword()
        {
            return View(User);
        }

        [HttpPost]
        public ActionResult SafePasswordSetting(SafePasswordModel model)
        {
            if (!ModelState.IsValid) return Error();
            if (User.ID != model.Id) return Error("信息错误");

            User user = _userService.GetUserByID(model.Id);
            if (user.SafePasswordPassed)
            {
                if (!model.SafePasswordOld.Hash().Equals(user.SafePassword))
                {
                    return Error("修改失败！安全密码不正确！");
                }
                user.ChangeSafePassword(model.SafePasswordOld, model.SafePassword);
            }
            else
            {
                user.BindSafePassword(model.SafePassword);
            }
            _userService.UpdateUser(user);
            return Success("账户修改成功");
        }

        public ActionResult BindPhone()
        {
            return View(User);
        }

        
        [HttpPost]
        public ActionResult PostBindPhone(int id, string mobile, string validateCode)
        {
            if (User.ID != id) return Error("信息错误");

            HttpCookie phone = Request.Cookies["mobile"];
            HttpCookie valicode = Request.Cookies["valicode"];

            if (valicode == null || phone == null)
            {
                return Error("验证码不正确！");
            }

            string valicodeValue = valicode.Value;
            string phoneValue = phone.Value;

            if (mobile.Hash().Hash() != phoneValue)
            {
                ModelState.AddModelError("", "手机号码不正确！");
                return Error("手机号码不正确！");
            }

            if (validateCode.Hash().Hash() != valicodeValue)
            {
                ModelState.AddModelError("", "验证码错误!");
                return Error("验证码不正确！");
            }

            User user = _userService.GetUserByID(id);
            user.Mobile = mobile;
            user.BindMobile(mobile);
            _userService.UpdateUser(user);

            Response.Cookies.Remove("valipass");

            return Success("手机绑定提交成功！");
        }

        public ActionResult BindIdCard()
        {
            return View(User);
        }

        [HttpPost]
        public ActionResult PostBindIdCard(IdcardSettingModel model)
        {
            if (!ModelState.IsValid) return Error();
            if (User.ID != model.Id) return Error("信息错误");

            User user = _userService.GetUserByID(model.Id);
            if (user.IDCardPassed)
            {
                return Error("身份证已验证，不能修改！");
            }
            if (user.IdValidatorTime >= 3)
            {
                return Error("身份证验证次数超过规定次数，请联系客服进行身份证验证！");
            }
            bool idHasPass = DbProvider.D<User>().Any(x => x.IDCardPassed && x.IDCard.Equals(model.IdCard) && x.GroupID==3);
            if (idHasPass)
            {
                return Error("此身份证已验证，不能重复验证！");
            }
            user.BindIDCard(model.IdCard, model.RealName);
            _userService.UpdateUser(user);
            return Success("", "身份认证成功！", Url.Action("Index"));
            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
            var validator = new QueryValidatorService();

            string userinfo = "{0},{1}".FormatWith(model.RealName, model.IdCard.ToUpper());
            string result = validator.querySingle("qiandaitong".ToDesEncrypt(), "qiandaitong_B97v_b6^".ToDesEncrypt(),
                                                  "1A020201".ToDesEncrypt(),
                                                  userinfo.ToDesEncrypt());
            if (!string.IsNullOrWhiteSpace(result))
            {
                string re = result.ToDesDecrypt();
                var xd = new XmlDocument();
                xd.LoadXml(re);
                XmlNode xmlRoot = xd.SelectSingleNode("data");
                if (xmlRoot != null)
                {
                    XmlNode messageNode = xmlRoot.ChildNodes[0];
                    string messageStatus = messageNode.ChildNodes[0].InnerText;
                    XmlNode checkInfosNode = xmlRoot.ChildNodes[1];
                    XmlNode checkInfoNode = checkInfosNode.ChildNodes[0];
                    string compStatus = checkInfoNode.ChildNodes[3].InnerText;

                    if (messageStatus == "0")
                    {
                        user.IdValidatorTime++;
                        if (compStatus == "3")
                        {
                            user.BindIDCard(model.IdCard, model.RealName);
                            _userService.UpdateUser(user);
                            return Success("", "身份认证成功！", Url.Action("Index"));
                        }
                        _userService.UpdateUser(user);
                        return Error("身份认证失败，请正确填写您的真实姓名和身份证号！");
                    }
                }
            }
            return Error("身份认证失败！");
        }


        #region 相关验证参数定义
        public enum subatmLength
        {
            application, version, sendTime, transCode, channelName, channelId, channelOrderId, factors, checkCode, checkResult, respCode, respDesc, idNumRight
        }
        private static string[] respCode = 
            {   
                "0000",	//验证成功（收费）
                "9999",	//未知错误（不收费）
                "9901",	//报文格式错误（不收费）
                "9902",	//解密错误（不收费）
                "9903",	//查无此应用（不收费）
                "9904",	//报文域不完整（不收费）
                "9921",	//报文域格式验证错误（不收费）
                "9922",	//身份验证错误（收费）
                "9923",	//卡号与姓名不匹配（收费）
                "9924",	//不支持该银行卡验证（不收费）
                "9925",	//银行卡手机验证错误（收费）
                "9926",	//实人认证错误（收费）
                "9927",	//验证失败或不支持手机号验证（收费）
                "9929",	//渠道订单号重复（不收费）
                "9930",	//发生异常（不收费）
                "9931",	//卡号与身份证号不匹配（收费）
                "9932"	//卡号与身份证号不支持验证（不收费）
            };
        private static string[] respCodeResult =
            {   
                "身份验证成功",	
                "未知错误",	
                "报文格式错误",	
                "解密错误",	
                "查无此应用",	
                "报文域不完整",	
                "报文域格式验证错误",	
                "身份验证错误",	
                "卡号与姓名不匹配",	
                "不支持该银行卡验证",	
                "银行卡手机验证错误",	
                "实人认证错误",	
                "验证失败或不支持手机号验证",	
                "渠道订单号重复",	
                "发生异常",	
                "卡号与身份证号不匹配",	
                "卡号与身份证号不支持验证"	
            };
        private string RightRespCodeInfo(string xmlResult)
        {
            if (xmlResult.Contains(respCode[1]))
                return (respCodeResult[1]);
            else if (xmlResult.Contains(respCode[2]))
                return (respCodeResult[2]);
            else if (xmlResult.Contains(respCode[3]))
                return (respCodeResult[3]);
            else if (xmlResult.Contains(respCode[4]))
                return (respCodeResult[4]);
            else if (xmlResult.Contains(respCode[5]))
                return (respCodeResult[5]);
            else if (xmlResult.Contains(respCode[6]))
                return (respCodeResult[6]);
            else if (xmlResult.Contains(respCode[7]))
                return (respCodeResult[7]);
            else if (xmlResult.Contains(respCode[8]))
                return (respCodeResult[8]);
            else if (xmlResult.Contains(respCode[9]))
                return (respCodeResult[9]);
            else if (xmlResult.Contains(respCode[10]))
                return (respCodeResult[10]);
            else if (xmlResult.Contains(respCode[11]))
                return (respCodeResult[11]);
            else if (xmlResult.Contains(respCode[12]))
                return (respCodeResult[12]);
            else if (xmlResult.Contains(respCode[13]))
                return (respCodeResult[13]);
            else if (xmlResult.Contains(respCode[14]))
                return (respCodeResult[14]);
            else if (xmlResult.Contains(respCode[15]))
                return (respCodeResult[15]);
            else if (xmlResult.Contains(respCode[16]))
                return (respCodeResult[16]);
            else return ("返回其它的错误信息，没有相应应答码，验证套餐输入格式错误，或者没有开通此业务！");
        }

        [HttpPost]
        public ActionResult PostBindIdCardHanxin(IdcardSettingModel model)
        {
            if (!ModelState.IsValid) return Error();
            if (User.ID != model.Id) return Error("信息错误");

            User user = _userService.GetUserByID(model.Id);
            if (user.IDCardPassed)
            {
                return Error("身份证已验证，不能修改！");
            }


            if (user.IdValidatorTime >= 3)
            {
                return Error("身份证验证次数超过规定次数，请联系客服进行身份证验证！");
            }

//            bool idHasPass = DbProvider.D<User>().Any(x => x.IDCardPassed && x.IDCard.Equals(model.IdCard) && x.GroupID == 3);
            bool idHasPass = DbProvider.D<User>().Any(x => x.IDCardPassed && x.IDCard.Equals(model.IdCard));
            if (idHasPass)
            {
                return Error("此身份证已验证，不能重复验证！");
            }

            /// 如果符合条件，开始最多三次验证
            string nowTime = DateTime.Now.ToString("yyyyMMddHHmmss");
            /// 这样就可以保证一次一密
            string mkey = new RandomKey().GenerateRandomNumber(24);
            string mkey16To23 = mkey.Substring(0, 8);
            /// 最大长度为30，可以更改，但是每次验证都不能重复，产生随机数之后就可以保证一次一密
            string channelOrderId = DateTime.Now.ToString("yyMMddHHmmssffff") + new RandomKey().GenerateRandomNumber(14);

            ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
            var validator = new QueryValidatorService();

            int intCheckCode = (int)QDT.Web.HanXinPlantFormInfo.PlantFormInfo.checkCodeTable.UserName_ID;
            string strFactors = QDT.Web.HanXinPlantFormInfo.PlantFormInfo.GetFactorsUserNameID(model.RealName, model.IdCard);
            string strCheckCode = intCheckCode.ToString();

            string xmlOriginalCode = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
                + "<subatm>"
                + "<application>GwBiz.Req</application>"
                + "<version>1.0.0</version>"
                + "<sendTime>"
                + nowTime
                + "</sendTime>"
                + "<transCode>"
                + QDT.Web.HanXinPlantFormInfo.PlantFormInfo.UserInfo.transCode
                + "</transCode>"
                + "<channelName>"
                + QDT.Web.HanXinPlantFormInfo.PlantFormInfo.UserInfo.channelName
                + "</channelName>"
                + "<channelId>"
                + QDT.Web.HanXinPlantFormInfo.PlantFormInfo.UserInfo.channelId           //翰鑫科技验证平台分配，不能更改
                + "</channelId>"
                + "<channelOrderId>"
                + channelOrderId                               //每次验证都不能重复
                + "</channelOrderId>"
                + "<factors>"
                + strFactors                                    //验证要素套餐，
                + "</factors>"
                + "<checkCode>"
                + strCheckCode                                  // 实名验证类型，要收费哦
                + "</checkCode>"
                + "</subatm>";
            /// 实现channelId的base64编码
            /// 翰鑫科技里就是default
            /// 因为byte是整数，所以不管你是default还是utf-8结果都是一样的
            /// byte[] btChannelId = UnicodeEncoding.UTF8.GetBytes(channelId);            
            byte[] btChannelId = UnicodeEncoding.Default.GetBytes(QDT.Web.HanXinPlantFormInfo.PlantFormInfo.UserInfo.channelId);
            string btChannelIdByBase64 = Convert.ToBase64String(btChannelId);

            /// 实现mkey密钥加密，就是渠道3Des算法密钥的加密，已经转换为Base64了
            string mKeyByRSAToBase64 = new RSAUtilSecurity().RSAEncrypt(mkey);
            /// 如果不行，下面这个是翰鑫平台默认的
            /// string mKeyByRSAToBase64 = new RSAUtilSecurity().RSAEncrypt(Encoding.UTF8.GetString(Encoding.Default.GetBytes(mkey)));


            /// 实现了原报文的加密，这里没有生成加密的密钥哦，已经转换为Base64了
            /// 这里secondkey.getBytes("utf-8")和secondkey.getBytes()结果一样，实在不行，就在C#中mkey改为default
            string xmlOriginalCodeByDES = new DesedeUtilSecurity().DesedeEncode(xmlOriginalCode, mkey, mkey16To23);
            //对应Java：String enCodeSecond = enCoderTo64.encode(DesUtil.encrypt(originalCode1.getBytes("utf-8"), secondkey.getBytes()));

            /// 生成了最终的加密报文，其加密报文体格式：BASE64(商户号)| BASE64(RSA(报文加密密钥))|BASE64(3DES(报文原文))
            string xmlTransfer = btChannelIdByBase64 + "|" + mKeyByRSAToBase64 + "|" + xmlOriginalCodeByDES;

            /// 服务器那边确实已经响应了，因为我改变URL的地址时，就会发生响应异常
            /// 发送请求和响应，读写数据
            string returnResult = new SendMsg().SendMsbReceiveResp(xmlTransfer);
            /// 查看实名验证是否成功
            if (!string.IsNullOrWhiteSpace(returnResult))
            {
                /// 在dos下|就是显示两个竖的虚线
                /// string[] xmlResult = Regex.Split(returnResult, "\\|", RegexOptions.IgnoreCase);
                string[] xmlResult = returnResult.Split('|');
                if (xmlResult[0] == "0")
                {
                    /// 用来调试用的
                    /// 响应错误，不用3DES解密了，只用BASE64Decoder解密就可以了
                    byte[] outputb = Convert.FromBase64String(xmlResult[2]);
                    string strByBase64 = Encoding.UTF8.GetString(outputb);
                    string strXmlResult = "应答错误，响应码是：" + xmlResult[1] + "，具体信息：" + strByBase64;
                    return Error(strXmlResult);
                }
                else
                {
                    // 响应正确，用3DES解密
                    // 因为byte是整数，所以不管你是default还是utf-8结果都是一样的
                    // 这里可以看一下mey的default和utf-8两种模式，看看结果是否一样，按翰鑫平台的话，应该是default，但是这们用的是utf-8
                    string strByDESDecode = new DesedeUtilSecurity().DesedeDecode(xmlResult[1], mkey, mkey16To23);//已经Base64解密了
                    /*-------------------------下面这种方法不严谨
                    if (strByDESDecode.Contains("respCode") && strByDESDecode.Contains(respCode[0]))
                        return Success("", "身份认证成功！", Url.Action("Index"));
                    else
                    { 
                        return Error(RightRespCodeInfo(strByDESDecode));
                    }*/
                    /// 用XmlDocument和XmlNode的方法，更严谨
                    var xd = new XmlDocument();
                    xd.LoadXml(strByDESDecode);
                    XmlNode xmlRoot = xd.SelectSingleNode("subatm");
                    if (xmlRoot != null)
                    {
                        XmlNode checkResultNode = xmlRoot.ChildNodes[(int)subatmLength.checkResult];
                        string strCheckResult = checkResultNode.ChildNodes[0].InnerText;
                        XmlNode respCodeNode = xmlRoot.ChildNodes[(int)subatmLength.respCode];
                        string strRespCode = respCodeNode.ChildNodes[0].InnerText;
                        if (strCheckResult == "1" && strRespCode == respCode[0])
                        {
                            /// 验证成功，如果一次成功就好，马上就更新                            
                            user.BindIDCard(model.IdCard, model.RealName);
                            _userService.UpdateUser(user);
                            return Success("", "身份认证成功！", Url.Action("Index"));
                        }
                        else
                        {
                            /// 验证失败，超过三次就要联系客服了
                            user.IdValidatorTime++;
                            _userService.UpdateUser(user);
                            return Error("身份认证失败，请正确填写您的真实姓名和身份证号！");
                        }
                    }
                }
            }
            return Error("身份认证失败！");
        }

        #endregion

        /// <summary>
        /// 自动投标
        /// </summary>
        /// <returns></returns>
        public ActionResult AutoBid()
        {
            UserAutoBid info = _userService.GetAutoBidByUserId(User.ID);
            info = info ?? new UserAutoBid();
            ViewBag.Money = User.UserAccount.Money;
            return View(info);
        }

        public ActionResult TurnAutoBid()
        {
            _userService.TurnOffAutoBid(User.ID);
            return Success("","",Url.Action("AutoBid"));
        }

        /// <summary>
        /// 自动投标设置
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AutoBidSetting(UserAutoBidModel model)
        {
            if (model.LoadMoney % 1 != 0)
            {
                return Error("投资金额需要填入正整数！");
            }
            _userService.SetAutoBid(User.ID, 0, model.LoadMoney, model.MinLoadMoney, model.DealDateUpperLimit,
                                    model.MoneyRateLowerLimit, model.RetainMoney, true, true);
            return Success("账户修改成功");
        }

        public ActionResult LazySettingAutoBid()
        {
            var modelid = 0;
            var set = DbProvider.D<UserAutoBid>().FirstOrDefault(x => x.UserId == User.ID);
            if (set != null) modelid = set.ID;
            _userService.SetAutoBid(User.ID, modelid, 1000, 1000, 12, 9, 0);
            return Success("设置成功", "", Url.Action("AutoBid"));
        }

        public ActionResult BindBankCard()
        {
            List<Bank> banks = DbProvider.D<Bank>().Where(x => x.IsEffect).ToList();

            List<RegionConfig> region = DbProvider.D<RegionConfig>().Where(x => x.Pid == 1).ToList();
            var regionLv2 = new List<SelectListItem> {new SelectListItem {Text = "省", Value = "0"}};
            region.Each(o =>
                            {
                                var i = new SelectListItem
                                            {Text = o.Name, Value = o.ID.ToString(CultureInfo.InvariantCulture)};
                                regionLv2.Add(i);
                            });
            ViewData["RegionLv2"] = regionLv2;

            ICollection<UserBank> userbanks = _userService.GetUserBank(User.ID);
            ViewData["UserBank"] = userbanks;
            ViewData["Banks"] = banks;

            return View(User);
        }

        public ActionResult PostBindBankCard(UserBankModel model)
        {
            if (!ModelState.IsValid) return Json(new { Info = "", Status=false }, JsonRequestBehavior.AllowGet);
            if (!User.IDCardPassed) return Json(new { Info = "请先实名认证", Status = false }, JsonRequestBehavior.AllowGet);
            if (string.IsNullOrWhiteSpace(model.BankCard)) return Json(new { Info = "请填写银行卡号", Status = false }, JsonRequestBehavior.AllowGet);
            if (model.BankId == 0) return Json(new { Info = "请选择银行卡开户银行", Status = false }, JsonRequestBehavior.AllowGet); 
            if (model.RegionLv3 == 0) return Json(new { Info = "请选择银行卡开户城市", Status = false }, JsonRequestBehavior.AllowGet);

            _userService.CreateUserBank(User.ID, model.BankId, model.BankCard.Replace(" ", ""),
                                        model.BankZone, 1,
                                        model.RegionLv2, model.RegionLv3, 0);
            if (User.MobilePassed)
            {
                var msg = new MsgQueueFactory().CreateBindBankMsg(User.Mobile, model.BankCard.ToConfuse(0, 6, 3));
                DbProvider.Add(msg);
                DbProvider.SaveChanges();
            }

            return Json(new { Info = "绑定银行卡成功！", Status = true }, JsonRequestBehavior.AllowGet);
        }

        public ActionResult DeleteBankCard(int bankid)
        {
            List<UserBank> userBanks = DbProvider.D<UserBank>().Where(x => x.UserId == User.ID).ToList();
            UserBank bank = userBanks.FirstOrDefault(x => x.ID == bankid);
            if (bank != null)
            {
                DbProvider.Delete(bank);
                DbProvider.SaveChanges();
                return Success("删除银行卡成功！");
            }
            return Success("删除银行卡失败！");
        }
        public ActionResult DefaultBankCard(int bankid)
        {
            var userBanks = DbProvider.D<UserBank>().Where(x => x.UserId == User.ID).ToList();
            var bank = userBanks.FirstOrDefault(x => x.ID == bankid);
            if (bank != null)
            {
                var defaultbank = userBanks.FirstOrDefault(x => x.IsDefault);
                if (defaultbank != null) defaultbank.IsDefault = false;
                bank.IsDefault = true;
                DbProvider.SaveChanges();
                return Success("设置默认银行卡成功！");
            }
            return Success("设置默认银行卡失败！");
        }

        public ActionResult BindEmail()
        {
            HttpCookie valipass = Request.Cookies["valipass"];

            if (User.EmailPassed)
            {
                if (valipass == null || string.IsNullOrWhiteSpace(valipass.Value))
                {
                    return RedirectToAction("ValidatePassWord", new { route = ChangeRoute.ChangeEmail });
                }
                if (User.SafePassword.Hash() != valipass.Value)
                {
                    return RedirectToAction("ValidatePassWord", new { route = ChangeRoute.ChangeEmail, error = true });
                }
                valipass.Value = null;
                Response.AppendCookie(valipass);
            }

            return View(User);
        }

        public ActionResult SendEmail(string email)
        {
            var isHas = DbProvider.D<User>().Any(x => x.Email == email && x.EmailPassed);
            if (isHas) return Error("邮箱已经存在，请重新输入！");

            var Ptime = DateTime.Now.Ticks;
            var Psign = email + Des.QDT_Key + Ptime;
            var activateUrl = MakeActiveUrl(Url.Action("PostBindEmail", "Account", new { id = User.ID, email, time = Ptime, sign = Psign.Hash().Hash() }));
            var content = PrepareMailBodyWith("BindEmail", "Email", email, "ActiveUrl", activateUrl);
            var msg = new MsgQueueFactory().CreateValidatorMsg(email, "众禧贷邮箱验证", content);
            msg.Level = 2;

            DbProvider.Add(msg);
            DbProvider.SaveChanges();
            return Success("","邮件发送成功，请登陆邮箱继续后续操作！", Url.Action("Index"));
        }

        private string PrepareMailBodyWith(string templateName, params string[] pairs)
        {
            string body = GetMailBodyOfTemplate(templateName);

            for (var i = 0; i < pairs.Length; i += 2)
            {
                body = body.Replace("<%={0}%>".FormatWith(pairs[i]), pairs[i + 1]);
            }

            body = body.Replace("<%=siteTitle%>", "众禧贷").Replace("<%=rootUrl%>", "");

            return body;
        }

        private string GetMailBodyOfTemplate(string templateName)
        {
            string body = string.Empty;
            if (string.IsNullOrEmpty(body))
            {
                body = ReadFileFrom(templateName);
            }
            return body;
        }

        private string ReadFileFrom(string templateName)
        {
            string templateDirectory = HostingEnvironment.IsHosted
            ? HostingEnvironment.MapPath("~/Content/EmailTemp") ?? ""
            : System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "EmailTemp");

            string filePath = string.Concat(System.IO.Path.Combine(templateDirectory, templateName), ".txt");

            string body = System.IO.File.ReadAllText(filePath);

            return body;
        }

        private string MakeActiveUrl(string action)
        {
            Uri requestUrl = Url.RequestContext.HttpContext.Request.Url;
            return "{0}://{1}{2}".FormatWith(requestUrl.Scheme, requestUrl.Authority, action);
        }

    }
}